package com.ikingtech.platform.service.oidc.endpoint.autorize;

import com.ikingtech.framework.sdk.utils.Tools;
import com.ikingtech.platform.service.oidc.client.service.OidcClientRedirectUriRepository;
import com.ikingtech.platform.service.oidc.client.service.OidcClientRepository;
import com.ikingtech.platform.service.oidc.exception.InvalidScopeException;
import com.ikingtech.platform.service.oidc.web.OidcAuthorizationRequest;
import com.ikingtech.platform.service.oidc.web.OidcAuthorizationResponse;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.MultiValueMap;

import java.util.concurrent.TimeUnit;

/**
 * @author tie yan
 */
public class OidcAuthorizationCodeRequestEndpoint extends AbstractOidcAuthorizeEndpoint {

    private final StringRedisTemplate redisTemplate;

    public OidcAuthorizationCodeRequestEndpoint(OidcClientRepository clientRepo,
                                                OidcClientRedirectUriRepository clientRedirectUriRepo,
                                                StringRedisTemplate redisTemplate) {
        super(clientRepo, clientRedirectUriRepo);
        this.redisTemplate = redisTemplate;
    }

    @Override
    protected OidcAuthorizationResponse doAuthorization(OidcAuthorizationRequest authorizationRequest) {
        OidcAuthorizationResponse authorizationResponse = new OidcAuthorizationResponse();
        authorizationResponse.setRedirectUri(authorizationRequest.getRedirectUri());
        authorizationResponse.setCode(Tools.Id.uuid());
        authorizationResponse.setState(authorizationRequest.getState());
        this.redisTemplate.opsForValue().set(Tools.Str.format("oidc:authorization_code:{}:{}", authorizationRequest.getClientId(), authorizationResponse.getCode()), Tools.Json.toJsonStr(authorizationRequest), 5, TimeUnit.MINUTES);
        return authorizationResponse;
    }

    @Override
    public OidcAuthorizationRequest convertRequest(MultiValueMap<String, String> paramMap) {
        OidcAuthorizationRequest authenticationRequest = super.convertRequest(paramMap);
        String scope = paramMap.getFirst(OidcAuthorizationRequest.AuthenticationRequestFieldName.SCOPE);
        if (Tools.Str.isBlank(scope) || !Tools.Str.split(scope).contains("openid")) {
            throw new InvalidScopeException();
        }
        authenticationRequest.setScope(scope);

        String state = paramMap.getFirst(OidcAuthorizationRequest.AuthenticationRequestFieldName.STATE);
        if (Tools.Str.isNotBlank(state)) {
            authenticationRequest.setState(state);
        }
        return authenticationRequest;
    }

    @Override
    public boolean support(String responseType) {
        return OidcAuthorizationRequest.AuthenticationRequestFieldName.CODE.equals(responseType);
    }
}
